package com.wei.czz.framework.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.dto.blog.BlogDto;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.po.blog.BlogManageListPo;
import com.wei.czz.common.po.blog.UserIssueBlogListPo;
import com.wei.czz.common.po.blog.audit.BlogAuditListPo;
import com.wei.czz.common.tool.PageQuery;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.CacheKeyUtils;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.blog.BlogManageFormVo;
import com.wei.czz.common.vo.blog.audit.BlogAuditFormVo;
import com.wei.czz.common.vo.blog.BlogFormVo;
import com.wei.czz.common.vo.blog.UserBlogFormVo;
import com.wei.czz.framework.blog.dao.BlogDao;
import com.wei.czz.framework.blog.entity.BlogEntity;
import com.wei.czz.framework.blog.service.BlogService;
import com.wei.czz.framework.common.handler.redis.RedisHashHandler;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.*;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.util.CollectionUtils;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2021-03-15 10:30:32
 * className: BlogServiceImpl 博客基本信息操作请求服务接口实现类
 * version: 1.0
 * description:
 */
@Service("blogService")
@AllArgsConstructor
public class BlogServiceImpl extends ServiceImpl<BlogDao, BlogEntity> implements BlogService {

    private static final Logger log = LoggerFactory.getLogger(BlogServiceImpl.class);

    private final RedisHashHandler redisHashHandler;

    @Override
    public void insert(BlogEntity blog) {
        // 获取操作用户
        String username = SecurityUtils.getOrDefaultUsername(StringUtils.EMPTY);
        Long userId = SecurityUtils.getOrDefaultUserId(CommonEnum.ZERO.getLongValue());
        Date date = new Date();

        blog.setDeleteStatus(CommonEnum.ZERO.getValue())
                .setUpdateTime(date)
                .setUpdateUser(username)
                .setUpdateUserId(userId)
                .setCreateTime(date)
                .setCreateUser(username)
                .setCreateUserId(userId);

        int count = baseMapper.insert(blog);
        log.info("保存博客完成。count={}", count);
    }

    @Override
    public Map<String, Object> getCacheBlogList(BlogFormVo blogFormVo) {
        // 查询Redis缓存，获取所有博客缓存键
        Set<String> blogIdSet = redisHashHandler.keys(CacheKeyUtils.getRedisHashKey(EntityConstant.BLOG));

        // 查询数据库系统博客基本表，获取所有博客id
        List<String> blogIdList = baseMapper.getBlogIdList();

        List<String> residueBlogIds = new ArrayList<>(blogIdList.size());
        // 数据库存储的数据和缓存数据进行取交集操作
        for (String roleId : blogIdList) {
            if (blogFormVo.getCacheStatus()) {
                // 查询已缓存数据
                if (blogIdSet.contains(roleId)) {
                    residueBlogIds.add(roleId);
                }
            } else {
                // 查询未缓存数据
                if (!blogIdSet.contains(roleId)) {
                    residueBlogIds.add(roleId);
                }
            }
        }
        // 构造mp分页对象
        Page<BlogDto> page = PageQuery.initPage(blogFormVo);

        if (!residueBlogIds.isEmpty()) {
            if (blogIdList.size() == residueBlogIds.size()) {
                residueBlogIds.clear();
            }

            // 查询数据库系统角色表，分页查询角色列表
            baseMapper.getCacheBlogList(page, residueBlogIds, blogFormVo);

        }

        Map<String, Object> result = new HashMap<>(8);
        result.put("cacheBlogSize", page.getTotal());
        result.put("page", new PageDto<>(page));
        return result;
    }

    @Override
    public BlogEntity getBlog(Long id) {
        // 查询数据库博客表，根据博客id获取博客对象
        BlogEntity blog = baseMapper.selectById(id);
        if (Objects.isNull(blog)) {
            log.info("博客不存在");
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "博客不存在，请确认");
        }
        if (CommonEnum.ONE.getValue().equals(blog.getDeleteStatus())) {
            log.info("博客已删除");
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "博客不存在，请确认");
        }
        return blog;
    }

    @Override
    public List<BlogEntity> getBlogList(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            log.info("查询博客，传递的博客id参数为空。idList={}", idList);
            return Collections.emptyList();
        }
        List<BlogEntity> blogList = baseMapper.selectBatchIds(idList);
        log.info("查询博客完成。list.size={}", blogList.size());
        return blogList;
    }

    @Override
    public List<BlogEntity> getBlogList() {
        LambdaQueryWrapper<BlogEntity> blogLambdaQueryWrapper = new LambdaQueryWrapper<>();
        blogLambdaQueryWrapper.eq(BlogEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        List<BlogEntity> blogList = baseMapper.selectList(blogLambdaQueryWrapper);
        log.info("查询全部博客完成。list.size={}", blogList.size());
        return blogList;
    }

    @Override
    public List<BlogEntity> getSpaceBlogList(List<Long> spaceIdList) {
        LambdaQueryWrapper<BlogEntity> blogLambdaWrapper = new LambdaQueryWrapper<>();
        // 匹配 空间id 字段
        blogLambdaWrapper.in(BlogEntity::getSpaceId, spaceIdList)
                .eq(BlogEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        List<BlogEntity> blogList = baseMapper.selectList(blogLambdaWrapper);
        if (blogList.isEmpty()) {
            log.info("空间关联博客列表为空。spaceIdList={}", spaceIdList);
        }
        return blogList;
    }

    @Override
    public PageDto<BlogEntity> getUserBlogPageList(UserBlogFormVo formVo) {
        if (Objects.isNull(formVo.getUserId())) {
            log.info("分页获取用户博客，传递的用户主键参数为空。{}", formVo);
            throw new CzzException("用户id不能为空");
        }

        // mp分页对象
        Page<BlogEntity> page = PageQuery.initPage(formVo);

        LambdaQueryWrapper<BlogEntity> blogLambdaQueryWrapper = new LambdaQueryWrapper<>();
        blogLambdaQueryWrapper.eq(BlogEntity::getUserId, formVo.getUserId())
                .eq(Objects.nonNull(formVo.getSpaceId()), BlogEntity::getSpaceId, formVo.getSpaceId())
                .eq(Objects.nonNull(formVo.getLabel()), BlogEntity::getLabel, formVo.getLabel())
                .eq(Objects.nonNull(formVo.getStatus()), BlogEntity::getStatus, formVo.getStatus())
                .like(StringUtils.isNotBlank(formVo.getWord()), BlogEntity::getTitle, formVo.getWord())
                .eq(BlogEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 分页查询
        baseMapper.selectPage(page, blogLambdaQueryWrapper);
        log.info("分页查询用户博客完成。totalNum={} list.size={}", page.getTotal(), page.getRecords().size());

        return new PageDto<>(page);
    }

    @Override
    public PageDto<UserIssueBlogListPo> getUserIssueBlogPageList(UserBlogFormVo formVo) {
        if (Objects.isNull(formVo.getUserId())) {
            log.info("分页获取用户已发布博客，传递的用户主键参数为空。{}", formVo);
            throw new CzzException("用户id不能为空");
        }

        // mp分页对象
        Page<UserIssueBlogListPo> page = PageQuery.initPage(formVo);
        // 分页查询
        baseMapper.selectUserIssueBlogPageList(page, formVo);
        log.info("分页查询用户已发布博客完成。totalNum={} list.size={}", page.getTotal(), page.getRecords().size());

        return new PageDto<>(page);
    }

    @Override
    public PageDto<BlogAuditListPo> getAuditPageList(BlogAuditFormVo formVo) {

        // mp分页对象
        Page<BlogAuditListPo> page = new Page<>(formVo.getPage(), formVo.getLimit());

        // 分页查询
        page = baseMapper.selectAuditPageList(page, formVo);
        log.info("分页查询博客审核记录完成。totalNum={} list.size={}", page.getTotal(), page.getRecords().size());

        return new PageDto<>(page);
    }

    @Override
    public PageDto<BlogManageListPo> getManageBlogPageList(BlogManageFormVo blogManageFormVo) {

        // mp分页对象
        Page<BlogManageListPo> page = PageQuery.initPage(blogManageFormVo);

        // 分页查询
        page = baseMapper.getManageBlogPageList(page, blogManageFormVo);
        log.info("分页查询博客管理列表完成。totalNum={} list.size={}", page.getTotal(), page.getRecords().size());

        return new PageDto<>(page);
    }

    @Override
    public void edit(BlogEntity blog) {
        // 获取操作用户
        String username = SecurityUtils.getOrDefaultUsername(StringUtils.EMPTY);
        Long userId = SecurityUtils.getOrDefaultUserId(CommonEnum.ZERO.getLongValue());
        Date date = new Date();

        blog.setUpdateTime(date)
                .setUpdateUser(username)
                .setUpdateUserId(userId);

        int count = baseMapper.updateById(blog);
        log.info("修改博客完成。count={}", count);
    }

    @Override
    public int incrementBlogViewNum(Long blogId, Integer num, Date updateTime, Long updateUserId) {
        return baseMapper.incrementBlogViewNum(blogId, num, updateTime, updateUserId);
    }

    @Override
    public int updateBlogLikeNum(Long blogId, Integer num, Date updateTime, Long updateUserId) {
        return baseMapper.updateBlogLikeNum(blogId, num, updateTime, updateUserId);
    }

    @Override
    public int updateBlogCollectNum(Long blogId, Integer num, Date updateTime, Long updateUserId) {
        return baseMapper.updateBlogCollectNum(blogId, num, updateTime, updateUserId);
    }

    @Override
    public int updateBlogCommentNum(Long blogId, Integer num, Date updateTime, Long updateUserId) {
        return baseMapper.updateBlogCommentNum(blogId, num, updateTime, updateUserId);
    }

    @Override
    public void deleteBlog(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            log.info("删除博客，传递的博客主键参数为空。{}", idList);
            return;
        }
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<BlogEntity> blogLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置 删除标记（’删除‘）、更新时间和操作更新的用户id 字段
        blogLambdaUpdateWrapper.set(BlogEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                .set(BlogEntity::getUpdateTime, date)
                .set(BlogEntity::getUpdateUser, userPo.getUsername())
                .set(BlogEntity::getUpdateUserId, userPo.getUserId());
        // 匹配 博客id（批量） 字段
        blogLambdaUpdateWrapper.in(BlogEntity::getId, idList)
                .eq(BlogEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 操作数据库系统博客基本表，根据博客id列表批量删除博客基础信息
        int count = baseMapper.update(blogLambdaUpdateWrapper);
        log.info("删除博客完成。count={}", count);
    }

}